package com.tmt.im.common.store;


import com.tmt.im.common.bean.DataSourceConfig;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.store.CacheStoreAdapter;
import org.apache.ignite.cache.store.CacheStoreSession;
import org.apache.ignite.resources.CacheStoreSessionResource;
import org.apache.ignite.resources.IgniteInstanceResource;

import javax.cache.integration.CacheWriterException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

/**
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/2 13:17
 * @Version 1.0
 **/
@Slf4j
@Getter
@Setter
public abstract class BaseCacheStoreAdapter<K, T> extends CacheStoreAdapter<K, T> {
    @IgniteInstanceResource
    private Ignite ignite;

    @CacheStoreSessionResource
    private CacheStoreSession session;

    private static DataSourceConfig dataSourceConfig;

    // Complete transaction or simply close connection if there is no transaction.
    @Override
    public void sessionEnd(boolean commit) {
        Connection conn = session.attachment();
        if (conn == null) {
            return;
        }
        try {
            if (conn.isClosed()) {
                return;
            }
            try {
                if (session.isWithinTransaction()) {
                    if (commit) {
                        conn.commit();
                    } else {
                        conn.rollback();
                    }
                }
            } finally {
                conn.close();
            }
        } catch (SQLException e) {
            throw new CacheWriterException("Failed to end store session.", e);
        }
    }

    // session if within a transaction.
    protected Connection connection() throws SQLException {
        if (session.isWithinTransaction()) {
            Connection conn = session.attachment();
            if (conn == null) {
                conn = openConnection(false);
                // Store connection in the session, so it can be accessed
                // for other operations within the same transaction.
                session.attach(conn);
            }
            return conn;
        }
        // Transaction can be null in case of simple load or put operation.
        return openConnection(true);
    }

    private Connection openConnection(boolean autoCommit) throws SQLException {
        if (dataSourceConfig == null) {
            // Open connection to your RDBMS systems (Oracle, MySQL, Postgres, DB2, Microsoft SQL, etc.)
            IgniteCache<String, Object> configParamCache = ignite.cache(Constant.APPLICATION_CONFIG_NAME);
            assert configParamCache != null;
            dataSourceConfig = (DataSourceConfig) configParamCache.get(Constant.DATA_SOURCE_CONFIG_NAME);
        }
        Connection conn = DriverManager.getConnection(dataSourceConfig.getUrl(), dataSourceConfig.getUserName(),
                dataSourceConfig.getPassword());
        conn.setAutoCommit(autoCommit);
        return conn;
    }

}
